#include "led.h"


#define USER_LED_TASK_PRIO 2			/* 定义任务优先级 */
#define USER_LED_TASK_STACK_SIZE 120	/* 定义任务堆栈大小 */
TaskHandle_t user_led_handle;			/* 定义任务句柄 */
void led_task(void* pvParameters); /* 任务函数 */
extern Led led;

/// @brief LED 构造函数，必须提供必要的参数
/// @param _gpiox 
/// @param _pins 
Led::Led(gpio_type* _gpiox, uint32_t _pins)
{
    xTaskCreate(
        (TaskFunction_t)led_task,
        (const char*)"led_task",
        (uint16_t)USER_LED_TASK_STACK_SIZE,
        (void*)NULL,
        (UBaseType_t)USER_LED_TASK_PRIO,
        (TaskHandle_t*)user_led_handle
    );

    m_gpiox = _gpiox;
    m_pins = _pins;
	if (_gpiox == GPIOA)
	{
		m_crm_periph_clock = CRM_GPIOA_PERIPH_CLOCK;
	}
    else if (_gpiox == GPIOB)
    {
        m_crm_periph_clock = CRM_GPIOB_PERIPH_CLOCK;
    }
    else if (_gpiox == GPIOC)
    {
        m_crm_periph_clock = CRM_GPIOC_PERIPH_CLOCK;
    }
    else if (_gpiox == GPIOD)
    {
        m_crm_periph_clock = CRM_GPIOD_PERIPH_CLOCK;
    }
}

/** @brief gpio config
  *	@biref LED IO Config
  */
void Led::gpio_config(void)
{
    /* 定义 GPIO 初始化结构体 */
    gpio_init_type gpio_init_struct;

    /* 使能 GPIOA 外设时钟 */
    crm_periph_clock_enable(m_crm_periph_clock, TRUE);

    /* 设置默认参数 */
    gpio_default_para_init(&gpio_init_struct);

    /* 配置 GPIO 参数 */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; /* 较大电流推动/吸入能力 */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; /* 推挽输出 */
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = m_pins;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(m_gpiox, &gpio_init_struct);
}

/// @brief led FreeRTOS 任务函数
/// @param pvParameters 
void led_task(void* pvParameters)
{
    led.gpio_config();
    uint32_t num = 0;
    uint32_t ul_notify_value;
    while (1)
    {
        ul_notify_value = ulTaskNotifyTake(pdTRUE, 0);
        if (ul_notify_value>0)
        {
            led.toggle();
        }
    }
}

void Led::toggle()
{
    m_gpiox->odt ^= m_pins;
}

void Led::on()
{
    gpio_bits_write(m_gpiox, m_pins, TRUE);
}

void Led::off()
{
    gpio_bits_write(m_gpiox, m_pins, FALSE);
}